import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter_web_study/api/app_config.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http_parser/http_parser.dart';
import 'package:image_picker/image_picker.dart';
import 'package:logger/logger.dart';
import 'service_api.dart';
import 'package:mime/mime.dart';
/*
 * 封装 restful 请求
 *
 * GET、POST、DELETE、PATCH
 * 主要作用为统一处理相关事务：
 *  - 统一处理请求前缀；
 *  - 统一打印请求信息；
 *  - 统一打印响应信息；
 *  - 统一打印报错信息；
 */
class DioUtils {
  static DioUtils? _instance;


  ///单例模式
  static DioUtils? getInstance() {
    if (_instance == null) {
      _instance = DioUtils._();
    }
    return _instance;
  }

  late BaseOptions options;
  late Dio dio;

  DioUtils._() {
    options = BaseOptions(
      // http://www.cairuoyu.com/api/p4/user/login
      baseUrl: AppConfig.BASE_URL,
      //连接服务器超时时间，单位是毫秒.
      connectTimeout: 1000 * 45,
      //响应流上前后两次接受到数据的间隔，单位为毫秒。
      receiveTimeout: 1000 * 45,
//      application/x-www-form-urlencoded格式编码,
      contentType: Headers.formUrlEncodedContentType,
      // headers: {
      //   // "Access-Control-Allow-Origin": "*",
      //   // "Access-Control-Allow-Credentials": true
      //   // 'Access-Control-Allow-Credentials': true,
      //   // "Access-Control-Allow-Headers":
      //   //     "Origin,Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,locale",
      //   // "Access-Control-Allow-Methods": "GET, HEAD, POST, OPTIONS",
      //   // "token": Constant.getToken(),
      // },
    );
    dio = Dio(options);
    dio.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志
    //拦截器   暂时没有用到的地方
    dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
      // Do something before request is sent
      return handler.next(options); //continue
      // 如果你想完成请求并返回一些自定义数据，你可以resolve一个Response对象 `handler.resolve(response)`。
      // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义response.
      //
      // 如果你想终止请求并触发一个错误,你可以返回一个`DioError`对象,如`handler.reject(error)`，
      // 这样请求将被中止并触发异常，上层catchError会被调用。
    }, onResponse: (response, handler) {
      // Do something with response data
      return handler.next(response); // continue
      // 如果你想终止请求并触发一个错误,你可以 reject 一个`DioError`对象,如`handler.reject(error)`，
      // 这样请求将被中止并触发异常，上层catchError会被调用。
    }, onError: (DioError e, handler) {
      // Do something with response error
      return handler.next(e); //continue
      // 如果你想完成请求并返回一些自定义数据，可以resolve 一个`Response`,如`handler.resolve(response)`。
      // 这样请求将会被终止，上层then会被调用，then中返回的数据将是你的自定义response.
    }));
  }

  DioUtils getUrl(UrlType value) {
    switch (value) {
      case UrlType.LOGINDOMAINNAME:
        options.baseUrl = AppConfig.BASE_URL;
        break;
      case UrlType.AUDITDOMAINNAME:
        options.baseUrl = AppConfig.BASE_URL1;
        break;
    }

    return this;
  }

  //get请求
  get(String url, Map<String, dynamic> params, Function successCallBack,
      Function errorCallBack) async {
    _requstHttp(url, successCallBack, 'get', params, errorCallBack);
  }

  //post请求
  post(String url, Map<String, dynamic> params, Function successCallBack,
      Function errorCallBack) async {
    _requstHttp(url, successCallBack, "post", params, errorCallBack);
  }

  _requstHttp(String url, Function successCallBack,
      [String? method,
      Map<String, dynamic>? params,
      Function? errorCallBack]) async {
    late Response response;
    // Map<String, dynamic> params = {};
    // if (ServiceApi.loginService != url) {
    //   params.putIfAbsent("token", () => "");
    //   params.putIfAbsent("session_uid", () => "");
    // }
    // params.addAll(map ?? {});
    try {
      if (method == 'get') {
        if (params != null && params.toString().isNotEmpty) {
          response = await dio.get(url, queryParameters: params);
        } else {
          response = await dio.get(url);
        }
      } else if (method == 'post') {
        if (params != null && params.toString().isNotEmpty) {
          response = await dio.post(url, data: params);
        } else {
          response = await dio.post(url);
        }
      }
    } on DioError catch (error) {
      // 请求错误处理
      Response? errorResponse;
      if (error.response != null) {
        errorResponse = error.response;
      } else {
        errorResponse = Response(
          statusCode: 666,
          requestOptions: error.requestOptions,
        );
      }
      // 请求超时
      if (error.type == DioErrorType.connectTimeout) {
        errorResponse?.statusCode = ResultCode.CONNECT_TIMEOUT;
      }
      // 一般服务器错误
      else if (error.type == DioErrorType.receiveTimeout) {
        errorResponse?.statusCode = ResultCode.RECEIVE_TIMEOUT;
      }

      // debug模式才打印
      if (AppConfig.DEBUG) {
        print('请求异常: ' + error.toString());
        print('请求异常url: ' + url);
        print('请求头: ' + dio.options.headers.toString());
        print('method: ' + dio.options.method);
      }
      _error(errorCallBack, error.message);
      return '';
    }
    // debug模式打印相关数据
    if (AppConfig.DEBUG) {
      // print('请求url: ' + url);
      print('请求头: ' + dio.options.headers.toString());
      if (params != null) {
        print('请求参数: ' + params.toString());
      }
      if (response != null) {
        Map<String, dynamic> dataMap2 = response.data is String
            ? json.decode(response.data)
            : response.data;
        Logger().d(dataMap2);
      }
    }
    Map<String, dynamic> dataMap = {};
    if (response.data is String) {
      dataMap = json.decode(response.data);
    } else {
      dataMap = response.data;
    }
    if (dataMap != null && dataMap['code'] == 0) {
      if (dataMap["data"] == null) {
        return;
      }
      successCallBack(dataMap);
    } else {
      Fluttertoast.showToast(msg: dataMap["message"]);
      _error(
          errorCallBack,
          '错误码：' +
              dataMap['errorCode'].toString() +
              '，' +
              response.data.toString());
    }
  }

  _error(Function? errorCallBack, String error) {
    if (errorCallBack != null) {
      errorCallBack(error);
    }
  }

  /// 上传文件
  Future uploadFile(XFile file, {onSendProgress}) async {
    String fileName = file.path.split('/').last;
    print('file = $file');
    print('fileName = $fileName');
    final mimeType = lookupMimeType(file.path, headerBytes: [0xFF, 0xD8])?.split('/');
    BaseOptions bo = BaseOptions(
      baseUrl: AppConfig.BASE_URL,
      //连接服务器超时时间，单位是毫秒.
      connectTimeout: 1000 * 45,
      //响应流上前后两次接受到数据的间隔，单位为毫秒。
      receiveTimeout: 1000 * 45,
    );
    bo.headers['Content-Type'] = 'multipart/form-data';


    Dio dioFile = Dio(bo);
    dioFile.interceptors.add(LogInterceptor(responseBody: false)); //开启请求日志
    // FormData formData = FormData.fromMap({
    //   "files.foo": await MultipartFile.fromFile(
    //     file.path,
    //     filename: file.path.split('/').last,
    //     contentType: MediaType(mimeType![0], mimeType[1]),
    //   ),
    // });
    //

  FormData formData = FormData.fromMap({"file":await MultipartFile.fromFile(file.path,filename: file.name)});

    Response response =
        await dioFile.post(ServiceApi.UPLOAD_FILE, data: formData,options: Options());
    if (response.data == null) {
      return;
    }
    Logger().d(jsonDecode(response.data));
    Map<String, dynamic> map = jsonDecode(response.data);
    if (map["code"] != 1) {
      Fluttertoast.showToast(msg: map["message"]);
      return;
    }
    return map["data"];
  }
}

/*
 * dio网络请求失败的回调错误码
 */
class ResultCode {
  //正常返回是1
  static const SUCCESS = 1;

  //异常返回是0
  static const ERROR = 1;

  /// 打开Url超时
  static const CONNECT_TIMEOUT = -1;

  ///接收超时时发生。
  static const RECEIVE_TIMEOUT = -2;

  /// 当服务器响应时，但状态不正确，例如404、503。。。
  static const RESPONSE = -3;

  /// 当请求被取消时，dio将抛出此类型的错误。
  static const CANCEL = -4;

  ///如果DioError.error不为空，则读取它。
  static const DEFAULT = -5;
}
